package com.originskyseed.platform.common.utils;

import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;

import com.alibaba.fastjson.JSONObject;
import com.originskyseed.platform.common.api.config.QrCodePathConfig;
import com.originskyseed.platform.core.config.bean.ConfigManager;
import com.originskyseed.platform.core.httpclient.bean.HttpMethodType;
import com.originskyseed.platform.core.httpclient.bean.HttpRequestTemplate;
import com.originskyseed.platform.core.tenant.util.TenantAppCodeUtil;
import com.originskyseed.platform.core.tenant.util.TenantCodeUtil;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;

/**
 * 文件服务器fastDfs工具类
 * 
 * @author ZhongJian 2021-02-01
 */
public class FastDfsUtil {

	/**
	 * 上传文件路径
	 */
	private static final String UPLOAD_URL_SUFFIX = "/file/upload.json";
	/**
	 * 默认文件服务器上传url
	 */
	private static final String DEFAULT_UPLOAD_URL = "http://file.originskyseed.com";

	/**
	 * 上传文件
	 * 
	 * @param bytes
	 * @return
	 * @throws Exception
	 */
	public static String upload(byte[] bytes, String fileName,String tokenId) throws Exception {
		ByteArrayBody byteArrayBody = new ByteArrayBody(bytes, fileName);
		// 获取租户域名配置
		QrCodePathConfig qrCodePathConfig = ConfigManager.getInstance().parseObject(QrCodePathConfig.class);
		String fileUrl = qrCodePathConfig == null || qrCodePathConfig.getUploadFileUrl() == null ? DEFAULT_UPLOAD_URL : qrCodePathConfig.getUploadFileUrl();
		String tenantCode=TenantCodeUtil.getInstance().getServerTenantCode()==null?"dy_dev":TenantCodeUtil.getInstance().getServerTenantCode();
		// 拼接文件服务器的url
		String api_timestamp=System.currentTimeMillis()+"";
		String api_nonce=genReqID();

		TreeMap<String,String> map = new TreeMap<>();
		map.put("api_timestamp",api_timestamp);
		map.put("api_nonce",api_nonce);
		map.put("tenant_code",tenantCode);
		map.put("system_type","core-admin");
		JSONObject json =JSONObject.parseObject(JSONObject.toJSONString(map));
		String md5Str=getServerSign(json);
		map.put("api_sign",md5Str);
		String url = fileUrl + UPLOAD_URL_SUFFIX;
		String tempParam = "";
		for (String key : map.keySet()) {
			if (key != null && StringUtils.isNotEmpty(key)) {
				String value = map.get(key) == null ? "" : map.get(key).toString();
				if (StringUtils.isNotEmpty(tempParam)) {
					tempParam = tempParam + "&" + key + "=" + URLEncoder.encode(value,"utf-8");
				} else {
					tempParam = tempParam + key + "=" + URLEncoder.encode(value,"utf-8");
				}
			}
		}
		if (tempParam != null && StringUtils.isNotEmpty(tempParam)) {
			url = url + "?" + tempParam;
		}
		CloseableHttpClient httpClient=null;
		CloseableHttpResponse httpResponse = null;
		httpClient = HttpClients.createDefault();
		//创建连接
		MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
		HttpPost httpPost = new HttpPost(url);
		multipartEntityBuilder.addPart("file",byteArrayBody);
		HttpEntity httpEntity = multipartEntityBuilder.build();
		httpPost.setEntity(httpEntity);
		httpPost.setHeader("Admin-TAMASTER-Originskyseed-SSO-Token",tokenId);
		httpResponse = httpClient.execute(httpPost);
		HttpEntity entity = httpResponse.getEntity();
		String result = EntityUtils.toString(entity);
		if (StringUtils.isNotBlank(result)) {
			JSONObject resultObj = JSONObject.parseObject(result);
			if (StringUtils.equals(resultObj.getString("code"), "1000")) {
				return resultObj.getString("data");
			}
		}
		return null;
	}

	public static String genReqID() {
		return UUID.randomUUID().toString().replace("-", "").toUpperCase();
	}

	/**
	 * 获取服务器签名
	 *
	 * @param params
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private static String getServerSign(JSONObject params) throws UnsupportedEncodingException {
		String result = null;

		if (null != params) {
			// 排除签名字段
			//params.remove(KEY_SIGN);

			// 递归排序编码
			String encodeStr = recursiveSortAndEncrypt(params);

			// 进行字符加密
			result = encrypt(encodeStr);
		}

		return result;
	}

	/**
	 * 递归排序加密
	 *
	 * @param object
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private static String recursiveSortAndEncrypt(Object object) throws UnsupportedEncodingException {
		StringBuilder result = new StringBuilder();
		if (object instanceof JSONObject) {
			JSONObject jsonObject = JSONObject.parseObject(object.toString());

			// 字典排序
			List<String> keys = new ArrayList<String>();
			keys.addAll(jsonObject.keySet());
			Collections.sort(keys);

			// 遍历对象
			for (int i = 0; i < keys.size(); i++) {
				String key = keys.get(i);
				String value = recursiveSortAndEncrypt(jsonObject.get(key));

				// 排除空字符串
				if (StringUtils.isNotBlank(value)) {
					result.append(key).append(value);
				}
			}
		} else if (object instanceof JSONArray) {
			JSONArray jsonArray = JSONArray.parseArray(object.toString());

			// 遍历对象
			for (int i = 0; i < jsonArray.size(); i++) {
				result.append(recursiveSortAndEncrypt(jsonArray.get(i)));
			}
		} else {
			result.append(URLEncoder.encode(object.toString(), "UTF-8").replaceAll("\\+", "%20")); // 特殊处理空格
		}
		return result.toString();
	}

	/**
	 * 加密
	 *
	 * @param str
	 * @return
	 */
	public static String encrypt(String str) {
		String result = "";

		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			if (null != messageDigest) {
				char[] charArray = str.toCharArray();
				byte[] byteArray = new byte[charArray.length];
				for (int i = 0; i < charArray.length; i++) {
					byteArray[i] = (byte) charArray[i];
				}
				byte[] md5Bytes = messageDigest.digest(byteArray);
				StringBuffer hexValue = new StringBuffer();
				for (int i = 0; i < md5Bytes.length; i++) {
					int val = ((int) md5Bytes[i]) & 0xff;
					if (val < 16) {
						hexValue.append("0");
					}
					hexValue.append(Integer.toHexString(val));
				}

				result = hexValue.toString();
			}
		} catch (Exception e) {
		}

		return result;
	}

}
